<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\Plugin\ChannelCode\Action\Workbench;

use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\Utils\Codec\Json;
use MoChat\App\Common\Constants\BusinessLog\Event;
use MoChat\App\Common\Contract\BusinessLogContract;
use MoChat\App\Common\Middleware\WorkbenchAuthMiddleware;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Request\ValidateSceneTrait;
use MoChat\Plugin\ChannelCode\Constants\Status;
use MoChat\Plugin\ChannelCode\Contract\ChannelCodeContract;
use MoChat\Plugin\ChannelCode\Logic\Traits\ChannelCodeTrait;

/**
 * 修改渠道码.
 *
 * Class Store
 * @Controller
 */
class Update extends AbstractAction
{
    use ValidateSceneTrait;
    use ChannelCodeTrait;

    /**
     * 渠道码表.
     * @Inject
     * @var ChannelCodeContract
     */
    private $channelCode;

    /**
     * @Inject
     * @var BusinessLogContract
     */
    private $businessLog;

    /**
     * @Inject
     * @var StdoutLoggerInterface
     */
    private $logger;

    /**
     * 参数.
     * @var array
     */
    private $params;

    /**
     * @Middlewares({
     *     @Middleware(WorkbenchAuthMiddleware::class)
     * })
     * @RequestMapping(path="/workbench/channelCode/update", methods="PUT")
     */
    public function handle(): array
    {
        $user = user();
        // 判断用户绑定企业信息
        if (! isset($user['corpId'])) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '未选择登录企业，不可操作');
        }
        $params['corpId'] = $user['corpId'];
        $params['employeeId'] = $user['id'];

        // 接收参数
        $params['type'] = (int) $this->request->input('type');
        $params['channelCodeId'] = $this->request->input('channelCodeId');
        $params['baseInfo'] = $this->request->input('baseInfo');
        $params['drainageEmployee'] = $this->request->input('drainageEmployee');
        $params['welcomeMessage'] = $this->request->input('welcomeMessage');
        $params['spanWelcomeStatus'] = (int) $this->request->input('spanWelcomeStatus');
        $params['welcomeMessage'] = $this->request->input('welcomeMessage');
        $params['spanWelcome'] = $this->request->input('spanWelcome');
        $params['closeWords'] = $this->request->input('closeWords', []);

        // 参数验证
        $this->validated($params);
        $this->params = $params;
        // 校验引流成员每个时间段配置的企业成员人数 （微信[联系我]中每个联系方式最多配置100个使用成员（包含部门展开后的成员））
        $this->checkEmployee();

        // 查询二维码微信配置id
        $info = $this->channelCode->getChannelCodeById(
            (int) $this->params['channelCodeId'],
            ['wx_config_id']
        );
        if (empty($info)) {
            throw new CommonException(ErrorCode::SERVER_ERROR, '查询不到渠道码信息');
        }
        // 开启事务
        Db::beginTransaction();
        try {
            // 编辑渠道码
            $this->updateChannelCode();
            // 记录日志
            $this->recordLog();

            Db::commit();
        } catch (\Throwable $ex) {
            Db::rollBack();
            $this->logger->error('编辑渠道码失败', $params);
        }

        // 更新二维码
        $this->handleQrCode(
            $this->params['drainageEmployee'],
            (int) $this->params['baseInfo']['autoAddFriend'],
            (int) $this->params['corpId'],
            (int) $this->params['channelCodeId'],
            $info['wxConfigId']
        );

        return [];
    }

    /**
     * 验证规则.
     *
     * @return array 响应数据
     */
    protected function rules(): array
    {
        return [
        ];
    }

    /**
     * 验证错误提示.
     * @return array 响应数据
     */
    protected function messages(): array
    {
        return [
        ];
    }

    /**
     * 编辑渠道码
     */
    private function updateChannelCode()
    {
        // 编辑参数
        $data = [
            'group_id' => $this->params['baseInfo']['groupId'],
            'auto_add_friend' => $this->params['baseInfo']['autoAddFriend'],
            'tags' => Json::encode($this->params['baseInfo']['tags']),
            'type' => $this->params['type'],
            'drainage_employee' => Json::encode($this->params['drainageEmployee']),
            'welcome_message' => Json::encode($this->params['welcomeMessage']),
            'span_welcome_status' => $this->params['spanWelcomeStatus'],
            'span_welcome' => isset($this->params['spanWelcome']) ? Json::encode($this->params['spanWelcome']) : '{}',
            'contact_remark' => isset($this->params['baseInfo']['contactRemark']) ? Json::encode($this->params['baseInfo']['contactRemark']) : '{}',
            'contact_description' => $this->params['baseInfo']['contactDescription'] ?? '',
            'close_words' => Json::encode($this->params['closeWords']),
            'image' => $this->params['baseInfo']['image'] ?? '',
        ];

        $res = $this->channelCode->updateChannelCodeById((int) $this->params['channelCodeId'], $data);
        if (! is_int($res)) {
            throw new CommonException(ErrorCode::SERVER_ERROR, '编辑渠道码失败');
        }
    }

    /**
     * 记录日志.
     */
    private function recordLog()
    {
        $params = [
            'channelCodeId' => $this->params['channelCodeId'],
            'baseInfo' => $this->params['baseInfo'],
            'drainageEmployee' => $this->params['drainageEmployee'],
            'welcomeMessage' => $this->params['welcomeMessage'],
        ];

        // 记录日志表
        $data = [
            'business_id' => $this->params['channelCodeId'],
            'params' => Json::encode($params),
            'event' => Event::CHANNEL_CODE_UPDATE,
            'operation_id' => $this->params['employeeId'],
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        $logRes = $this->businessLog->createBusinessLog($data);
        if (! is_int($logRes)) {
            throw new CommonException(ErrorCode::SERVER_ERROR, '编辑渠道码日志记录失败');
        }
    }

    /**
     * 校验每个时间段配置的企业成员人数.
     * @return array|bool
     */
    private function checkEmployee()
    {
        // 类型不需要校验
        if ($this->params['drainageEmployee']['addMax']['status'] === Status::CLOSE) {
            return [];
        }

        // 处理客户添加上限
        if ($this->params['drainageEmployee']['addMax']['status'] === Status::OPEN) {
            foreach ($this->params['drainageEmployee']['addMax']['employees'] as $item) {
                if ($item['max'] > 20000) {
                    throw new CommonException(ErrorCode::SERVER_ERROR, '每日添加客户上限为20000');
                }
            }
        }
        return true;
    }
}
